home *** CD-ROM | disk | FTP | other *** search
/ Aminet 40 / Aminet 40 (2000)(Schatztruhe)[!][Dec 2000].iso / Aminet / dev / lang / Python16.lha / Python-1.6 / Lib / Python1.6 / pickle.py < prev    next >
Encoding:
Python Source  |  2000-03-11  |  22.7 KB  |  895 lines

  1. """Create portable serialized representations of Python objects.
  2.  
  3. See module cPickle for a (much) faster implementation.
  4. See module copy_reg for a mechanism for registering custom picklers.
  5.  
  6. Classes:
  7.  
  8.     Pickler
  9.     Unpickler
  10.  
  11. Functions:
  12.  
  13.     dump(object, file)
  14.     dumps(object) -> string
  15.     load(file) -> object
  16.     loads(string) -> object
  17.  
  18. Misc variables:
  19.  
  20.     __version__
  21.     format_version
  22.     compatible_formats
  23.  
  24. """
  25.  
  26. __version__ = "$Revision: 1.37 $"       # Code version
  27.  
  28. from types import *
  29. from copy_reg import dispatch_table, safe_constructors
  30. import string
  31. import marshal
  32. import sys
  33. import struct
  34.  
  35. format_version = "1.3"                     # File format version we write
  36. compatible_formats = ["1.0", "1.1", "1.2"] # Old format versions we can read
  37.  
  38. mdumps = marshal.dumps
  39. mloads = marshal.loads
  40.  
  41. PicklingError = "pickle.PicklingError"
  42. UnpicklingError = "pickle.UnpicklingError"
  43.  
  44. try:
  45.     from org.python.core import PyStringMap
  46. except ImportError:
  47.     PyStringMap = None
  48.  
  49. MARK            = '('
  50. STOP            = '.'
  51. POP             = '0'
  52. POP_MARK        = '1'
  53. DUP             = '2'
  54. FLOAT           = 'F'
  55. INT             = 'I'
  56. BININT          = 'J'
  57. BININT1         = 'K'
  58. LONG            = 'L'
  59. BININT2         = 'M'
  60. NONE            = 'N'
  61. PERSID          = 'P'
  62. BINPERSID       = 'Q'
  63. REDUCE          = 'R'
  64. STRING          = 'S'
  65. BINSTRING       = 'T'
  66. SHORT_BINSTRING = 'U'
  67. UNICODE         = 'V'
  68. BINUNICODE      = 'X'
  69. APPEND          = 'a'
  70. BUILD           = 'b'
  71. GLOBAL          = 'c'
  72. DICT            = 'd'
  73. EMPTY_DICT      = '}'
  74. APPENDS         = 'e'
  75. GET             = 'g'
  76. BINGET          = 'h'
  77. INST            = 'i'
  78. LONG_BINGET     = 'j'
  79. LIST            = 'l'
  80. EMPTY_LIST      = ']'
  81. OBJ             = 'o'
  82. PUT             = 'p'
  83. BINPUT          = 'q'
  84. LONG_BINPUT     = 'r'
  85. SETITEM         = 's'
  86. TUPLE           = 't'
  87. EMPTY_TUPLE     = ')'
  88. SETITEMS        = 'u'
  89. BINFLOAT        = 'G'
  90.  
  91. class Pickler:
  92.  
  93.     def __init__(self, file, bin = 0):
  94.         self.write = file.write
  95.         self.memo = {}
  96.         self.bin = bin
  97.  
  98.     def dump(self, object):
  99.         self.save(object)
  100.         self.write(STOP)
  101.  
  102.     def put(self, i):
  103.         if (self.bin):
  104.             s = mdumps(i)[1:]
  105.             if (i < 256):
  106.                 return BINPUT + s[0]
  107.  
  108.             return LONG_BINPUT + s
  109.  
  110.         return PUT + `i` + '\n'
  111.  
  112.     def get(self, i):
  113.         if (self.bin):
  114.             s = mdumps(i)[1:]
  115.  
  116.             if (i < 256):
  117.                 return BINGET + s[0]
  118.  
  119.             return LONG_BINGET + s
  120.  
  121.         return GET + `i` + '\n'
  122.         
  123.     def save(self, object, pers_save = 0):
  124.         memo = self.memo
  125.  
  126.         if (not pers_save):
  127.             pid = self.persistent_id(object)
  128.             if (pid is not None):
  129.                 self.save_pers(pid)
  130.                 return
  131.  
  132.         d = id(object)
  133.  
  134.         t = type(object)
  135.  
  136.         if ((t is TupleType) and (len(object) == 0)):
  137.             if (self.bin):
  138.                 self.save_empty_tuple(object)
  139.             else:
  140.                 self.save_tuple(object)
  141.             return
  142.  
  143.         if memo.has_key(d):
  144.             self.write(self.get(memo[d][0]))
  145.             return
  146.  
  147.         try:
  148.             f = self.dispatch[t]
  149.         except KeyError:
  150.             pid = self.inst_persistent_id(object)
  151.             if pid is not None:
  152.                 self.save_pers(pid)
  153.                 return
  154.  
  155.             try:
  156.                 reduce = dispatch_table[t]
  157.             except KeyError:
  158.                 try:
  159.                     reduce = object.__reduce__
  160.                 except AttributeError:
  161.                     raise PicklingError, \
  162.                         "can't pickle %s object: %s" % (`t.__name__`,
  163.                                                          `object`)
  164.                 else:
  165.                     tup = reduce()
  166.             else:
  167.                 tup = reduce(object)
  168.  
  169.             if type(tup) is StringType:
  170.                 self.save_global(object, tup)
  171.                 return
  172.  
  173.             if (type(tup) is not TupleType):
  174.                 raise PicklingError, "Value returned by %s must be a " \
  175.                                      "tuple" % reduce
  176.  
  177.             l = len(tup)
  178.    
  179.             if ((l != 2) and (l != 3)):
  180.                 raise PicklingError, "tuple returned by %s must contain " \
  181.                                      "only two or three elements" % reduce
  182.  
  183.             callable = tup[0]
  184.             arg_tup  = tup[1]
  185.           
  186.             if (l > 2):
  187.                 state = tup[2]
  188.             else:
  189.                 state = None
  190.  
  191.             if type(arg_tup) is not TupleType and arg_tup is not None:
  192.                 raise PicklingError, "Second element of tuple returned " \
  193.                                      "by %s must be a tuple" % reduce
  194.  
  195.             self.save_reduce(callable, arg_tup, state) 
  196.             memo_len = len(memo)
  197.             self.write(self.put(memo_len))
  198.             memo[d] = (memo_len, object)
  199.             return
  200.  
  201.         f(self, object)
  202.  
  203.     def persistent_id(self, object):
  204.         return None
  205.  
  206.     def inst_persistent_id(self, object):
  207.         return None
  208.  
  209.     def save_pers(self, pid):
  210.         if (not self.bin):
  211.             self.write(PERSID + str(pid) + '\n')
  212.         else:
  213.             self.save(pid, 1)
  214.             self.write(BINPERSID)
  215.  
  216.     def save_reduce(self, callable, arg_tup, state = None):
  217.         write = self.write
  218.         save = self.save
  219.  
  220.         save(callable)
  221.         save(arg_tup)
  222.         write(REDUCE)
  223.         
  224.         if (state is not None):
  225.             save(state)
  226.             write(BUILD)
  227.  
  228.     dispatch = {}
  229.  
  230.     def save_none(self, object):
  231.         self.write(NONE)
  232.     dispatch[NoneType] = save_none
  233.  
  234.     def save_int(self, object):
  235.         if (self.bin):
  236.             i = mdumps(object)[1:]
  237.             if (i[-2:] == '\000\000'):
  238.                 if (i[-3] == '\000'):
  239.                     self.write(BININT1 + i[:-3])
  240.                     return
  241.  
  242.                 self.write(BININT2 + i[:-2])
  243.                 return
  244.  
  245.             self.write(BININT + i)
  246.         else:
  247.             self.write(INT + `object` + '\n')
  248.     dispatch[IntType] = save_int
  249.  
  250.     def save_long(self, object):
  251.         self.write(LONG + `object` + '\n')
  252.     dispatch[LongType] = save_long
  253.  
  254.     def save_float(self, object, pack=struct.pack):
  255.         if self.bin:
  256.             self.write(BINFLOAT + pack('>d', object))
  257.         else:
  258.             self.write(FLOAT + `object` + '\n')
  259.     dispatch[FloatType] = save_float
  260.  
  261.     def save_string(self, object):
  262.         d = id(object)
  263.         memo = self.memo
  264.  
  265.         if (self.bin):
  266.             l = len(object)
  267.             s = mdumps(l)[1:]
  268.             if (l < 256):
  269.                 self.write(SHORT_BINSTRING + s[0] + object)
  270.             else:
  271.                 self.write(BINSTRING + s + object)
  272.         else:
  273.             self.write(STRING + `object` + '\n')
  274.  
  275.         memo_len = len(memo)
  276.         self.write(self.put(memo_len))
  277.         memo[d] = (memo_len, object)
  278.     dispatch[StringType] = save_string
  279.  
  280.     def save_unicode(self, object):
  281.         d = id(object)
  282.         memo = self.memo
  283.  
  284.         if (self.bin):
  285.             encoding = object.encode('utf-8')
  286.             l = len(encoding)
  287.             s = mdumps(l)[1:]
  288.             self.write(BINUNICODE + s + encoding)
  289.         else:
  290.             self.write(UNICODE + object.encode('raw-unicode-escape') + '\n')
  291.  
  292.         memo_len = len(memo)
  293.         self.write(self.put(memo_len))
  294.         memo[d] = (memo_len, object)
  295.     dispatch[UnicodeType] = save_unicode
  296.  
  297.     def save_tuple(self, object):
  298.  
  299.         write = self.write
  300.         save  = self.save
  301.         memo  = self.memo
  302.  
  303.         d = id(object)
  304.  
  305.         write(MARK)
  306.  
  307.         for element in object:
  308.             save(element)
  309.  
  310.         if (len(object) and memo.has_key(d)):
  311.             if (self.bin):
  312.                 write(POP_MARK + self.get(memo[d][0]))
  313.                 return
  314.            
  315.             write(POP * (len(object) + 1) + self.get(memo[d][0]))
  316.             return
  317.  
  318.         memo_len = len(memo)
  319.         self.write(TUPLE + self.put(memo_len))
  320.         memo[d] = (memo_len, object)
  321.     dispatch[TupleType] = save_tuple
  322.  
  323.     def save_empty_tuple(self, object):
  324.         self.write(EMPTY_TUPLE)
  325.  
  326.     def save_list(self, object):
  327.         d = id(object)
  328.  
  329.         write = self.write
  330.         save  = self.save
  331.         memo  = self.memo
  332.  
  333.         if (self.bin):
  334.             write(EMPTY_LIST)
  335.         else:
  336.             write(MARK + LIST)
  337.  
  338.         memo_len = len(memo)
  339.         write(self.put(memo_len))
  340.         memo[d] = (memo_len, object)
  341.  
  342.         using_appends = (self.bin and (len(object) > 1))
  343.  
  344.         if (using_appends):
  345.             write(MARK)
  346.  
  347.         for element in object:
  348.             save(element)
  349.   
  350.             if (not using_appends):
  351.                 write(APPEND)
  352.  
  353.         if (using_appends):
  354.             write(APPENDS)
  355.     dispatch[ListType] = save_list
  356.  
  357.     def save_dict(self, object):
  358.         d = id(object)
  359.  
  360.         write = self.write
  361.         save  = self.save
  362.         memo  = self.memo
  363.  
  364.         if (self.bin):
  365.             write(EMPTY_DICT)
  366.         else:
  367.             write(MARK + DICT)
  368.  
  369.         memo_len = len(memo)
  370.         self.write(self.put(memo_len))
  371.         memo[d] = (memo_len, object)
  372.  
  373.         using_setitems = (self.bin and (len(object) > 1))
  374.  
  375.         if (using_setitems):
  376.             write(MARK)
  377.  
  378.         items = object.items()
  379.         for key, value in items:
  380.             save(key)
  381.             save(value)
  382.  
  383.             if (not using_setitems):
  384.                 write(SETITEM)
  385.  
  386.         if (using_setitems):
  387.             write(SETITEMS)
  388.  
  389.     dispatch[DictionaryType] = save_dict
  390.     if not PyStringMap is None:
  391.         dispatch[PyStringMap] = save_dict
  392.  
  393.     def save_inst(self, object):
  394.         d = id(object)
  395.         cls = object.__class__
  396.  
  397.         memo  = self.memo
  398.         write = self.write
  399.         save  = self.save
  400.  
  401.         if hasattr(object, '__getinitargs__'):
  402.             args = object.__getinitargs__()
  403.             len(args) # XXX Assert it's a sequence
  404.             _keep_alive(args, memo)
  405.         else:
  406.             args = ()
  407.  
  408.         write(MARK)
  409.  
  410.         if (self.bin):
  411.             save(cls)
  412.  
  413.         for arg in args:
  414.             save(arg)
  415.  
  416.         memo_len = len(memo)
  417.         if (self.bin):
  418.             write(OBJ + self.put(memo_len))
  419.         else:
  420.             write(INST + cls.__module__ + '\n' + cls.__name__ + '\n' +
  421.                 self.put(memo_len))
  422.  
  423.         memo[d] = (memo_len, object)
  424.  
  425.         try:
  426.             getstate = object.__getstate__
  427.         except AttributeError:
  428.             stuff = object.__dict__
  429.         else:
  430.             stuff = getstate()
  431.             _keep_alive(stuff, memo)
  432.         save(stuff)
  433.         write(BUILD)
  434.     dispatch[InstanceType] = save_inst
  435.  
  436.     def save_global(self, object, name = None):
  437.         write = self.write
  438.         memo = self.memo
  439.  
  440.         if (name is None):
  441.             name = object.__name__
  442.  
  443.         try:
  444.             module = object.__module__
  445.         except AttributeError:
  446.             module = whichmodule(object, name)
  447.  
  448.         memo_len = len(memo)
  449.         write(GLOBAL + module + '\n' + name + '\n' +
  450.             self.put(memo_len))
  451.         memo[id(object)] = (memo_len, object)
  452.     dispatch[ClassType] = save_global
  453.     dispatch[FunctionType] = save_global
  454.     dispatch[BuiltinFunctionType] = save_global
  455.  
  456.  
  457. def _keep_alive(x, memo):
  458.     """Keeps a reference to the object x in the memo.
  459.  
  460.     Because we remember objects by their id, we have
  461.     to assure that possibly temporary objects are kept
  462.     alive by referencing them.
  463.     We store a reference at the id of the memo, which should
  464.     normally not be used unless someone tries to deepcopy
  465.     the memo itself...
  466.     """
  467.     try:
  468.         memo[id(memo)].append(x)
  469.     except KeyError:
  470.         # aha, this is the first one :-)
  471.         memo[id(memo)]=[x]
  472.  
  473.  
  474. classmap = {}
  475.  
  476. # This is no longer used to find classes, but still for functions
  477. def whichmodule(cls, clsname):
  478.     """Figure out the module in which a class occurs.
  479.  
  480.     Search sys.modules for the module.
  481.     Cache in classmap.
  482.     Return a module name.
  483.     If the class cannot be found, return __main__.
  484.     """
  485.     if classmap.has_key(cls):
  486.         return classmap[cls]
  487.  
  488.     for name, module in sys.modules.items():
  489.         if name != '__main__' and \
  490.             hasattr(module, clsname) and \
  491.             getattr(module, clsname) is cls:
  492.             break
  493.     else:
  494.         name = '__main__'
  495.     classmap[cls] = name
  496.     return name
  497.  
  498.  
  499. class Unpickler:
  500.  
  501.     def __init__(self, file):
  502.         self.readline = file.readline
  503.         self.read = file.read
  504.         self.memo = {}
  505.  
  506.     def load(self):
  507.         self.mark = ['spam'] # Any new unique object
  508.         self.stack = []
  509.         self.append = self.stack.append
  510.         read = self.read
  511.         dispatch = self.dispatch
  512.         try:
  513.             while 1:
  514.                 key = read(1)
  515.                 dispatch[key](self)
  516.         except STOP, value:
  517.             return value
  518.  
  519.     def marker(self):
  520.         stack = self.stack
  521.         mark = self.mark
  522.         k = len(stack)-1
  523.         while stack[k] is not mark: k = k-1
  524.         return k
  525.  
  526.     dispatch = {}
  527.  
  528.     def load_eof(self):
  529.         raise EOFError
  530.     dispatch[''] = load_eof
  531.  
  532.     def load_persid(self):
  533.         pid = self.readline()[:-1]
  534.         self.append(self.persistent_load(pid))
  535.     dispatch[PERSID] = load_persid
  536.  
  537.     def load_binpersid(self):
  538.         stack = self.stack
  539.          
  540.         pid = stack[-1]
  541.         del stack[-1]
  542.  
  543.         self.append(self.persistent_load(pid))
  544.     dispatch[BINPERSID] = load_binpersid
  545.  
  546.     def load_none(self):
  547.         self.append(None)
  548.     dispatch[NONE] = load_none
  549.  
  550.     def load_int(self):
  551.         self.append(string.atoi(self.readline()[:-1]))
  552.     dispatch[INT] = load_int
  553.  
  554.     def load_binint(self):
  555.         self.append(mloads('i' + self.read(4)))
  556.     dispatch[BININT] = load_binint
  557.  
  558.     def load_binint1(self):
  559.         self.append(mloads('i' + self.read(1) + '\000\000\000'))
  560.     dispatch[BININT1] = load_binint1
  561.  
  562.     def load_binint2(self):
  563.         self.append(mloads('i' + self.read(2) + '\000\000'))
  564.     dispatch[BININT2] = load_binint2
  565.  
  566.     def load_long(self):
  567.         self.append(string.atol(self.readline()[:-1], 0))
  568.     dispatch[LONG] = load_long
  569.  
  570.     def load_float(self):
  571.         self.append(string.atof(self.readline()[:-1]))
  572.     dispatch[FLOAT] = load_float
  573.  
  574.     def load_binfloat(self, unpack=struct.unpack):
  575.         self.append(unpack('>d', self.read(8))[0])
  576.     dispatch[BINFLOAT] = load_binfloat
  577.  
  578.     def load_string(self):
  579.         self.append(eval(self.readline()[:-1],
  580.                          {'__builtins__': {}})) # Let's be careful
  581.     dispatch[STRING] = load_string
  582.  
  583.     def load_binstring(self):
  584.         len = mloads('i' + self.read(4))
  585.         self.append(self.read(len))
  586.     dispatch[BINSTRING] = load_binstring
  587.  
  588.     def load_unicode(self):
  589.         self.append(unicode(self.readline()[:-1],'raw-unicode-escape'))
  590.     dispatch[UNICODE] = load_unicode
  591.  
  592.     def load_binunicode(self):
  593.         len = mloads('i' + self.read(4))
  594.         self.append(unicode(self.read(len),'utf-8'))
  595.     dispatch[BINUNICODE] = load_binunicode
  596.  
  597.     def load_short_binstring(self):
  598.         len = mloads('i' + self.read(1) + '\000\000\000')
  599.         self.append(self.read(len))
  600.     dispatch[SHORT_BINSTRING] = load_short_binstring
  601.  
  602.     def load_tuple(self):
  603.         k = self.marker()
  604.         self.stack[k:] = [tuple(self.stack[k+1:])]
  605.     dispatch[TUPLE] = load_tuple
  606.  
  607.     def load_empty_tuple(self):
  608.         self.stack.append(())
  609.     dispatch[EMPTY_TUPLE] = load_empty_tuple
  610.  
  611.     def load_empty_list(self):
  612.         self.stack.append([])
  613.     dispatch[EMPTY_LIST] = load_empty_list
  614.  
  615.     def load_empty_dictionary(self):
  616.         self.stack.append({})
  617.     dispatch[EMPTY_DICT] = load_empty_dictionary
  618.  
  619.     def load_list(self):
  620.         k = self.marker()
  621.         self.stack[k:] = [self.stack[k+1:]]
  622.     dispatch[LIST] = load_list
  623.  
  624.     def load_dict(self):
  625.         k = self.marker()
  626.         d = {}
  627.         items = self.stack[k+1:]
  628.         for i in range(0, len(items), 2):
  629.             key = items[i]
  630.             value = items[i+1]
  631.             d[key] = value
  632.         self.stack[k:] = [d]
  633.     dispatch[DICT] = load_dict
  634.  
  635.     def load_inst(self):
  636.         k = self.marker()
  637.         args = tuple(self.stack[k+1:])
  638.         del self.stack[k:]
  639.         module = self.readline()[:-1]
  640.         name = self.readline()[:-1]
  641.         klass = self.find_class(module, name)
  642.         instantiated = 0
  643.         if (not args and type(klass) is ClassType and
  644.             not hasattr(klass, "__getinitargs__")):
  645.             try:
  646.                 value = _EmptyClass()
  647.                 value.__class__ = klass
  648.                 instantiated = 1
  649.             except RuntimeError:
  650.                 # In restricted execution, assignment to inst.__class__ is
  651.                 # prohibited
  652.                 pass
  653.         if not instantiated:
  654.             try:
  655.                 value = apply(klass, args)
  656.             except TypeError, err:
  657.                 raise TypeError, "in constructor for %s: %s" % (
  658.                     klass.__name__, str(err)), sys.exc_info()[2]
  659.         self.append(value)
  660.     dispatch[INST] = load_inst
  661.  
  662.     def load_obj(self):
  663.         stack = self.stack
  664.         k = self.marker()
  665.         klass = stack[k + 1]
  666.         del stack[k + 1]
  667.         args = tuple(stack[k + 1:]) 
  668.         del stack[k:]
  669.         instantiated = 0
  670.         if (not args and type(klass) is ClassType and
  671.             not hasattr(klass, "__getinitargs__")):
  672.             try:
  673.                 value = _EmptyClass()
  674.                 value.__class__ = klass
  675.                 instantiated = 1
  676.             except RuntimeError:
  677.                 # In restricted execution, assignment to inst.__class__ is
  678.                 # prohibited
  679.                 pass
  680.         if not instantiated:
  681.             value = apply(klass, args)
  682.         self.append(value)
  683.     dispatch[OBJ] = load_obj                
  684.  
  685.     def load_global(self):
  686.         module = self.readline()[:-1]
  687.         name = self.readline()[:-1]
  688.         klass = self.find_class(module, name)
  689.         self.append(klass)
  690.     dispatch[GLOBAL] = load_global
  691.  
  692.     def find_class(self, module, name):
  693.         try:
  694.             __import__(module)
  695.             mod = sys.modules[module]
  696.             klass = getattr(mod, name)
  697.         except (ImportError, KeyError, AttributeError):
  698.             raise SystemError, \
  699.                   "Failed to import class %s from module %s" % \
  700.                   (name, module)
  701.         return klass
  702.  
  703.     def load_reduce(self):
  704.         stack = self.stack
  705.  
  706.         callable = stack[-2]
  707.         arg_tup  = stack[-1]
  708.         del stack[-2:]
  709.  
  710.         if type(callable) is not ClassType:
  711.             if not safe_constructors.has_key(callable):
  712.                 try:
  713.                     safe = callable.__safe_for_unpickling__
  714.                 except AttributeError:
  715.                     safe = None
  716.  
  717.                 if (not safe):
  718.                    raise UnpicklingError, "%s is not safe for " \
  719.                                           "unpickling" % callable
  720.  
  721.         if arg_tup is None:
  722.             value = callable.__basicnew__()
  723.         else:
  724.             value = apply(callable, arg_tup)
  725.         self.append(value)
  726.     dispatch[REDUCE] = load_reduce
  727.  
  728.     def load_pop(self):
  729.         del self.stack[-1]
  730.     dispatch[POP] = load_pop
  731.  
  732.     def load_pop_mark(self):
  733.         k = self.marker()
  734.         del self.stack[k:]
  735.     dispatch[POP_MARK] = load_pop_mark
  736.  
  737.     def load_dup(self):
  738.         self.append(self.stack[-1])
  739.     dispatch[DUP] = load_dup
  740.  
  741.     def load_get(self):
  742.         self.append(self.memo[self.readline()[:-1]])
  743.     dispatch[GET] = load_get
  744.  
  745.     def load_binget(self):
  746.         i = mloads('i' + self.read(1) + '\000\000\000')
  747.         self.append(self.memo[`i`])
  748.     dispatch[BINGET] = load_binget
  749.  
  750.     def load_long_binget(self):
  751.         i = mloads('i' + self.read(4))
  752.         self.append(self.memo[`i`])
  753.     dispatch[LONG_BINGET] = load_long_binget
  754.  
  755.     def load_put(self):
  756.         self.memo[self.readline()[:-1]] = self.stack[-1]
  757.     dispatch[PUT] = load_put
  758.  
  759.     def load_binput(self):
  760.         i = mloads('i' + self.read(1) + '\000\000\000')
  761.         self.memo[`i`] = self.stack[-1]
  762.     dispatch[BINPUT] = load_binput
  763.  
  764.     def load_long_binput(self):
  765.         i = mloads('i' + self.read(4))
  766.         self.memo[`i`] = self.stack[-1]
  767.     dispatch[LONG_BINPUT] = load_long_binput
  768.  
  769.     def load_append(self):
  770.         stack = self.stack
  771.         value = stack[-1]
  772.         del stack[-1]
  773.         list = stack[-1]
  774.         list.append(value)
  775.     dispatch[APPEND] = load_append
  776.  
  777.     def load_appends(self):
  778.         stack = self.stack
  779.         mark = self.marker()
  780.         list = stack[mark - 1]
  781.         for i in range(mark + 1, len(stack)):
  782.             list.append(stack[i])
  783.  
  784.         del stack[mark:]
  785.     dispatch[APPENDS] = load_appends
  786.            
  787.     def load_setitem(self):
  788.         stack = self.stack
  789.         value = stack[-1]
  790.         key = stack[-2]
  791.         del stack[-2:]
  792.         dict = stack[-1]
  793.         dict[key] = value
  794.     dispatch[SETITEM] = load_setitem
  795.  
  796.     def load_setitems(self):
  797.         stack = self.stack
  798.         mark = self.marker()
  799.         dict = stack[mark - 1]
  800.         for i in range(mark + 1, len(stack), 2):
  801.             dict[stack[i]] = stack[i + 1]
  802.  
  803.         del stack[mark:]
  804.     dispatch[SETITEMS] = load_setitems
  805.  
  806.     def load_build(self):
  807.         stack = self.stack
  808.         value = stack[-1]
  809.         del stack[-1]
  810.         inst = stack[-1]
  811.         try:
  812.             setstate = inst.__setstate__
  813.         except AttributeError:
  814.             try:
  815.                 inst.__dict__.update(value)
  816.             except RuntimeError:
  817.                 # XXX In restricted execution, the instance's __dict__ is not
  818.                 # accessible.  Use the old way of unpickling the instance
  819.                 # variables.  This is a semantic different when unpickling in
  820.                 # restricted vs. unrestricted modes.
  821.                 for k, v in value.items():
  822.                     setattr(inst, k, v)
  823.         else:
  824.             setstate(value)
  825.     dispatch[BUILD] = load_build
  826.  
  827.     def load_mark(self):
  828.         self.append(self.mark)
  829.     dispatch[MARK] = load_mark
  830.  
  831.     def load_stop(self):
  832.         value = self.stack[-1]
  833.         del self.stack[-1]
  834.         raise STOP, value
  835.     dispatch[STOP] = load_stop
  836.  
  837. # Helper class for load_inst/load_obj
  838.  
  839. class _EmptyClass:
  840.     pass
  841.  
  842. # Shorthands
  843.  
  844. from StringIO import StringIO
  845.  
  846. def dump(object, file, bin = 0):
  847.     Pickler(file, bin).dump(object)
  848.  
  849. def dumps(object, bin = 0):
  850.     file = StringIO()
  851.     Pickler(file, bin).dump(object)
  852.     return file.getvalue()
  853.  
  854. def load(file):
  855.     return Unpickler(file).load()
  856.  
  857. def loads(str):
  858.     file = StringIO(str)
  859.     return Unpickler(file).load()
  860.  
  861.  
  862. # The rest is used for testing only
  863.  
  864. class C:
  865.     def __cmp__(self, other):
  866.         return cmp(self.__dict__, other.__dict__)
  867.  
  868. def test():
  869.     fn = 'out'
  870.     c = C()
  871.     c.foo = 1
  872.     c.bar = 2
  873.     x = [0, 1, 2, 3]
  874.     y = ('abc', 'abc', c, c)
  875.     x.append(y)
  876.     x.append(y)
  877.     x.append(5)
  878.     f = open(fn, 'w')
  879.     F = Pickler(f)
  880.     F.dump(x)
  881.     f.close()
  882.     f = open(fn, 'r')
  883.     U = Unpickler(f)
  884.     x2 = U.load()
  885.     print x
  886.     print x2
  887.     print x == x2
  888.     print map(id, x)
  889.     print map(id, x2)
  890.     print F.memo
  891.     print U.memo
  892.  
  893. if __name__ == '__main__':
  894.     test()
  895.